﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;

namespace Pws.Clients.RestLibrary.Transport
{
	/*
	 * Copyright (C) PWS Distributors Ltd 2011-2013
	 * All rights reserved.
	 * 
	 */

	/// <summary>
	/// An example implementation of a library which executes PWS Rest Web Service calls.
	/// It may be used either with Xml or with the Pws.Clients.RestLibrary objects.
	/// 
	/// Instances and operations are thread safe.
	/// </summary>
	public interface IRequestFactory
	{
		#region Core methods
		/// <summary>
		/// The location of the main deployment, depending on the DeploymentType being used.
		/// E.g. http://services.pws.co.uk:8080/rest or http://services.pws.co.uk:8080/rest-staging
		/// </summary>
		String DeploymentUri { get; }

		/// <summary>
		/// Perform a REST Web Service call to PWS, without any user authentication methods.
		/// </summary>
		/// <param name="requestMethod">HTTP request type, e.g. GET or POST.</param>
		/// <param name="service">The absolute URI to the service and object being called. </param>
		/// <param name="requestMediaType">The request type of the request message content. May be null, if no messageContent is being sent. E.g. application/x.pws.customers.orders.order-v1+xml</param>
		/// <param name="responseMediaType">The response type to expect in return. E.g. application/x.pws.customers.orders.order-v1+xml</param>
		/// <param name="messageContent">Request message content. Must be null for a GET operation.</param>
		/// <returns>WebResponse object. This must be Disposed once finished with.</returns>
		[System.Runtime.InteropServices.ComVisible(false)]
		WebResponse GetRestResponse(string requestMethod, Uri service, string requestMediaType, string responseMediaType, Stream messageContent);

		/// <summary>
		/// Perform a REST Web Service call to PWS, with token based user authentication. The HMAC is also included in the request, implicitly.
		/// </summary>
		/// <param name="requestMethod">HTTP request type, e.g. GET or POST.</param>
		/// <param name="service">The absolute URI to the service and object being called. </param>
		/// <param name="requestMediaType">The request type of the request message content. May be null, if no messageContent is being sent. E.g. application/x.pws.customers.orders.order-v1+xml</param>
		/// <param name="responseMediaType">The response type to expect in return. E.g. application/x.pws.customers.orders.order-v1+xml</param>
		/// <param name="messageContent">Request message content. Must be null for a GET operation.</param>
		/// <param name="token">A user authentication token which has been provided by the PWS Authentication Token Service.</param>
		/// <returns>WebResponse object. This must be Disposed once finished with.</returns>
		[System.Runtime.InteropServices.ComVisible(false)]
		WebResponse GetRestResponse(string requestMethod, Uri service, string requestMediaType, string responseMediaType, Stream messageContent, string token);

		/// <summary>
		/// Perform a REST Web Service call to PWS, with token based user authentication. The HMAC is also included in the request, implicitly.
		/// </summary>
		/// <param name="requestMethod">HTTP request type, e.g. GET or POST.</param>
		/// <param name="service">The absolute URI to the service and object being called. </param>
		/// <param name="requestMediaType">The request type of the request message content. May be null, if no messageContent is being sent. E.g. application/x.pws.customers.orders.order-v1+xml</param>
		/// <param name="responseMediaType">The response type to expect in return. E.g. application/x.pws.customers.orders.order-v1+xml</param>
		/// <param name="messageContent">Request message content. Must be null for a GET operation.</param>
		/// <param name="username">The end user's username to use for authentication.</param>
		/// <param name="password">The end user's password to use for authentication.</param>
		/// <param name="sendHmac">True to specify that a HMAC should be calculated and sent in the request header.</param>
		/// <returns>WebResponse object. This must be Disposed once finished with.</returns>
		[System.Runtime.InteropServices.ComVisible(false)]
		WebResponse GetRestResponse(string requestMethod, Uri service, string requestMediaType, string responseMediaType, Stream messageContent, string username, string password);
		#endregion

		#region Simplified wrapper methods
		/// <summary>
		/// Perform a REST Web Service call to PWS, with token based user authentication. The HMAC is also included in the request, implicitly.
		/// This will attempt to use the DataContractSerializer on the supplied and retrieved objects.
		/// </summary>
		/// <param name="requestMethod">HTTP request type, e.g. GET or POST.</param>
		/// <param name="service">The absolute URI to the service and object being called. </param>
		/// <param name="mediaType">The response type to expect in return, and optionally for sending (if applicable). E.g. application/x.pws.customers.orders.order-v1+xml</param>
		/// <param name="sendObject">The object to send, if applicable. Must be null for a GET operation.</param>
		/// <param name="token">A user authentication token which has been provided by the PWS Authentication Token Service.</param>
		/// <returns>A deserialised object of type T. If this is not possible, then an exception is thrown.</returns>
		/// <exception cref="SerializationException">Thrown if the response did not contain an object of type T.</exception>
		/// <typeparam name="T">The type of object being received (and optionally sent). This will be used for automatic serialisation to Xml.</typeparam>
		[System.Runtime.InteropServices.ComVisible(false)]
		T GetRestResponseAsObject<T>(string requestMethod, Uri service, string mediaType, T sendObject, string token) where T : class;

		/// <summary>
		/// Perform a REST Web Service call to PWS, with token based user authentication. The HMAC is also included in the request, implicitly.
		/// This will attempt to use the DataContractSerializer on the retrieved object, with the supplied data being sent from a stream; useful for a Post of binary data.
		/// </summary>
		/// <param name="requestMethod">HTTP request type, e.g. GET or POST.</param>
		/// <param name="service">The absolute URI to the service and object being called. </param>
		/// <param name="mediaTypeRequest">The request type to use for sending the binary data, e.g. image/png</param>
		/// <param name="mediaTypeResponse">The response type to expect in return.</param>
		/// <param name="sendData">The data to send. Must be null for a GET operation.</param>
		/// <param name="token">A user authentication token which has been provided by the PWS Authentication Token Service.</param>
		/// <param name="httpResponseHeaders">Returns the HTTP headers that were received with the response.</param>
		/// <returns>A deserialised object of type T. If this is not possible, then an exception is thrown.</returns>
		/// <exception cref="SerializationException">Thrown if the response did not contain an object of type T.</exception>
		/// <typeparam name="T">The type of object being received. This will be used for automatic deserialisation to Xml.</typeparam>
		[System.Runtime.InteropServices.ComVisible(false)]
		T GetRestResponseAsObject<T>(string requestMethod, Uri service, string mediaTypeRequest, string mediaTypeResponse, Stream sendData, string token, out WebHeaderCollection httpResponseHeaders) where T : class;

		/// <summary>
		/// Perform a REST Web Service call to PWS, with token based user authentication. The HMAC is also included in the request, implicitly.
		/// This will attempt to use the DataContractSerializer on the supplied and retrieved objects.
		/// </summary>
		/// <param name="requestMethod">HTTP request type, e.g. GET or POST.</param>
		/// <param name="service">The absolute URI to the service and object being called. </param>
		/// <param name="mediaType">The response type to expect in return, and optionally for sending (if applicable). E.g. application/x.pws.customers.orders.order-v1+xml</param>
		/// <param name="sendObject">The object to send, if applicable. Must be null for a GET operation.</param>
		/// <param name="token">A user authentication token which has been provided by the PWS Authentication Token Service.</param>
		/// <param name="httpResponseHeaders">Returns the HTTP headers that were received with the response.</param>
		/// <returns>A deserialised object of type T. If this is not possible, then an exception is thrown.</returns>
		/// <exception cref="SerializationException">Thrown if the response did not contain an object of type T.</exception>
		/// <typeparam name="T">The type of object being received (and optionally sent). This will be used for automatic serialisation to Xml.</typeparam>
		[System.Runtime.InteropServices.ComVisible(false)]
		T GetRestResponseAsObject<T>(string requestMethod, Uri service, string mediaType, T sendObject, string token, out WebHeaderCollection httpResponseHeaders) where T : class;

		/// <summary>
		/// Perform a REST Web Service call to PWS, with basic authentication. The HMAC is also included in the request, implicitly.
		/// This will attempt to use the DataContractSerializer on the supplied and retrieved objects.
		/// </summary>
		/// <param name="requestMethod">HTTP request type, e.g. GET or POST.</param>
		/// <param name="service">The absolute URI to the service and object being called. </param>
		/// <param name="mediaType">The response type to expect in return, and optionally for sending (if applicable). E.g. application/x.pws.customers.orders.order-v1+xml</param>
		/// <param name="sendObject">The object to send, if applicable. Must be null for a GET operation.</param>
		/// <param name="username">The end user's username to use for authentication.</param>
		/// <param name="password">The end user's password to use for authentication.</param>
		/// <returns>A deserialised object of type T. If this is not possible, then an exception is thrown.</returns>
		/// <exception cref="SerializationException">Thrown if the response did not contain an object of type T.</exception>
		/// <typeparam name="T">The type of object being received (and optionally sent). This will be used for automatic serialisation to Xml.</typeparam>
		[System.Runtime.InteropServices.ComVisible(false)]
		T GetRestResponseAsObject<T>(string requestMethod, Uri service, string mediaType, T sendObject, string username, string password) where T : class;
		#endregion

		#region COM specific methods
		/// <summary>
		/// For use only with COM. Sets the API key directly rather than through the constructor.
		/// </summary>
		/// <param name="apiKeyGuid">A string representation of a GUID.</param>
		void SetApiKey(String apiKeyGuid);

		/// <summary>
		/// For use only with COM. Sets the private key directly rather than through the constructor.
		/// </summary>
		/// <param name="privateKeyGuid">A string representation of a GUID.</param>
		void SetPrivateKey(String privateKeyGuid);

		/// <summary>
		/// Perform a REST Web Service call to PWS, with basic authentication. The HMAC is also included in the request, implicitly.
		/// This will transact in a string which is assumed to contain Xml.
		/// </summary>
		/// <param name="requestMethod">HTTP request type, e.g. GET or POST.</param>
		/// <param name="service">The absolute URI to the service and object being called. </param>
		/// <param name="mediaType">The response type to expect in return, and optionally for sending (if applicable). E.g. application/x.pws.customers.orders.order-v1+xml</param>
		/// <param name="sendObject">The object to send, if applicable, as an Xml string. Must be null for a GET operation.</param>
		/// <param name="username">The end user's username to use for authentication.</param>
		/// <param name="password">The end user's password to use for authentication.</param>
		/// <returns>An Xml string representation. If this is not possible, then an exception is thrown.</returns>
		String GetRestResponseAsXml(string requestMethod, string service, string mediaType, string sendObject, string username, string password);

		/// <summary>
		/// Perform a REST Web Service call to PWS, with token based user authentication. The HMAC is also included in the request, implicitly.
		/// This will transact in a string which is assumed to contain Xml.
		/// </summary>
		/// <param name="requestMethod">HTTP request type, e.g. GET or POST.</param>
		/// <param name="service">The absolute URI to the service and object being called. </param>
		/// <param name="mediaType">The response type to expect in return, and optionally for sending (if applicable). E.g. application/x.pws.customers.orders.order-v1+xml</param>
		/// <param name="sendObject">The object to send, if applicable, as an Xml string. Must be null for a GET operation.</param>
		/// <param name="username">The end user's username to use for authentication.</param>
		/// <param name="password">The end user's password to use for authentication.</param>
		/// <returns>An Xml string representation. If this is not possible, then an exception is thrown.</returns>
		String GetRestResponseAsXml(string requestMethod, string service, string mediaType, string sendObject, string token);
		#endregion
	}
}
